package com.ldy.transmit.filter;

import java.io.IOException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.RequestDispatcher;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.annotation.WebFilter;
import javax.servlet.http.HttpServletRequest;

import com.ldy.transmit.common.util.AppUtil;
import com.ldy.transmit.model.Transmit;
import com.ldy.transmit.model.TransmitExample;
import com.ldy.transmit.service.TransmitService;
import org.apache.commons.lang.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;


/**
 * @author 初哥
 *	转发请求类，将originalUrl的请求转发到对应的destination上面
 */

@Component
@WebFilter(urlPatterns = "/*", filterName = "TransmitFilter")
public class TransmitFilter implements Filter{
	
	private Logger LOGGER = LoggerFactory.getLogger(TransmitFilter.class);
	
	private Map<String, List<Transmit>> APP_TRANSMITS_MAP = new ConcurrentHashMap<>();
	
	private static final String API = "/api";
	
	private static final Pattern PATTERN = Pattern.compile("^/(.*)/api/([v|V]\\d+)/(.*)");
	/**
	 * 查询字符串结尾的/
	 */
	private static final Pattern PATTERN_SLASH = Pattern.compile("(?<=[^/]*)(/+)$");
	//@Autowired
	private TransmitService transmitService;
	
	@Override
	public void init(FilterConfig filterConfig) throws ServletException {
		//this.transmitService = AppUtil.getBean(TransmitService.class);
		if(transmitService != null) {
			List<Transmit> transmits = null;
			try {
				transmits = this.transmitService.selectByExample(new TransmitExample());
			}catch (Exception e) {
				LOGGER.error("get transmit data occurs an error ------>", e);
			}
			if(transmits != null && !transmits.isEmpty()) {
				for (Transmit transmit : transmits) {
					if(APP_TRANSMITS_MAP.get(transmit.getAppName()) == null) {
						APP_TRANSMITS_MAP.put(transmit.getAppName(), new ArrayList<Transmit>());
					}
					transmit.setOrginalUrl(removeSlash(transmit.getOrginalUrl()));
					transmit.setDestinationUrl(removeSlash(transmit.getDestinationUrl()));
					APP_TRANSMITS_MAP.get(transmit.getAppName()).add(transmit);
				}
			}
		}
	}
	private static String removeSlash(String orginalUrl) {
		while(StringUtils.startsWith(orginalUrl, "/")) {
			orginalUrl = orginalUrl.substring(1, orginalUrl.length());
		}
		while(StringUtils.endsWith(orginalUrl, "/")) {
			orginalUrl = orginalUrl.substring(0, orginalUrl.length()-1);
		}
		return orginalUrl;
	}
public static void main(String[] args) {
//	System.out.println(removeLastSlash("/owsp/api/V3/mobile/bpm/tasks/backlogs//////"));
//	Pattern compile = Pattern.compile("(?<=[^/]*)(/+)$");
//	System.out.println(compile.matcher("/owsp/api/V3/mobile/bpm/tasks/backlogs").find());
//	Matcher matcher = compile.matcher("/owsp/api/V3/mobile/bpm/tasks/backlogs////");
//	if(matcher.find()) {
//		for(int i=0;i<=matcher.groupCount();i++) {
//			System.out.println(matcher.group(i));
//		}
//	}
	Matcher matcher = PATTERN.matcher("/owsp/api/V3/mobile/bpm/tasks/backlogs");
	if(matcher.find()) {
		System.out.println(matcher.group(0));
		System.out.println(matcher.group(1));
		System.out.println(matcher.group(2));
		System.out.println(matcher.group(3));
	}
}
	@Override
	public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
			throws IOException, ServletException {
		HttpServletRequest httpServletRequest = (HttpServletRequest)request;
		LOGGER.info("接收到请求地址 ： ====={}", httpServletRequest.getRequestURL());
		String requestURI = httpServletRequest.getRequestURI();
		String contextPath = httpServletRequest.getContextPath();
		if(StringUtils.isNotBlank(requestURI)) {
			requestURI = requestURI.substring(contextPath.length(), requestURI.length());
			String appName = "";
			String version = "";
			String orginalUri = "";
			Matcher matcher = PATTERN.matcher(requestURI);
			if(matcher.find()) {
				System.out.println(matcher.group(0));
				appName = matcher.group(1);
				version = matcher.group(2);
				orginalUri = matcher.group(3);
			}
			Transmit transmit = findTransmit(appName, version, orginalUri);
			if (transmit != null) {
				LOGGER.info("准备转发请求： {} =====>> {}", httpServletRequest.getRequestURL(), transmit.getDestinationUrl());
				httpServletRequest = new LdyHttpServletRequest(httpServletRequest, transmit.getDestinationUrl());
				if(StringUtils.contains(requestURI,"/sfimimgload/") && "GET".equals(httpServletRequest.getMethod().toUpperCase())) {
					httpServletRequest.getRequestDispatcher("/sfimimgload").forward(httpServletRequest, response);
				}else {
					RequestDispatcher requestDispatcher =httpServletRequest.getRequestDispatcher("/greatdoors");
					requestDispatcher.forward(httpServletRequest, response);
				}
				return;
			}
		}
		chain.doFilter(request, response);
	}

	private Transmit findTransmit(String appName, String version, String orginalUri) {
		//测试直接用空，不加缓存
		List<Transmit> transmits = Collections.emptyList();//APP_TRANSMITS_MAP.get(appName);
//		if(transmits == null || transmits.isEmpty()) {
//			TransmitExample example = new TransmitExample();
//			example.or().andAppNameEqualTo(appName).andVersionEqualTo(version);
//			List<Transmit> dbTransmits = transmitService.selectByExample(example);
//			if(dbTransmits != null && !dbTransmits.isEmpty()) {
//				for (Transmit transmit : dbTransmits) {
//					transmit.setOrginalUrl(removeSlash(transmit.getOrginalUrl()));
//					transmit.setDestinationUrl(removeSlash(transmit.getDestinationUrl()));
//					if (StringUtils.equals(orginalUri, transmit.getOrginalUrl())) {
//						return transmit;
//					}
//				}
//				APP_TRANSMITS_MAP.put(appName, dbTransmits);
//			}
//			return null;
//		}else {
//			for (Transmit transmit : transmits) {
//				if(StringUtils.equals(orginalUri, removeSlash(transmit.getOrginalUrl()))) {
//					return transmit;
//				}
//			}
//		}
		return null;
	}
	@Override
	public void destroy() {
		APP_TRANSMITS_MAP = null;
	}

}
